Skip to content

Add method='datashader' to render_images for sparse images#676

Open
timtreis wants to merge 6 commits into
mainfrom
fix/issue-449
Open

Add method='datashader' to render_images for sparse images#676
timtreis wants to merge 6 commits into
mainfrom
fix/issue-449

Conversation

@timtreis
Copy link
Copy Markdown
Member

@timtreis timtreis commented May 20, 2026

Summary

  • Closes Feature: datashader also for images #449. Adds method='datashader' and ds_reduction kwargs to render_images() so very sparse images (mostly zeros, rare non-zero pixels) survive the downsample step instead of being averaged to near-black by the default mean-aggregating rasterization + imshow interpolation. Mirrors the existing render_points/render_shapes API.
  • Routes the rasterization step through datashader.Canvas.raster with a configurable downsample method (default 'max'); forces imshow(interpolation='nearest') on that path so the chosen reduction isn't re-smoothed at display time. Geometry + spatial transformations are inherited from spatialdata.rasterize so the output integrates cleanly with the existing transform plumbing.
  • Centralizes _DsReduction (previously inline-duplicated across 5 sites) into render_params.py, alongside a new _ImageDsReduction for the image-only valid set (mode, first, last added; sum, any, count removed since they're not valid Canvas.raster downsample_method values).

API addition (purely additive, defaults preserve current behavior)

render_images(
    ...,
    method: Literal["matplotlib", "datashader"] | None = None,
    ds_reduction: Literal["max", "min", "mean", "mode", "first", "last", "var", "std"] | None = None,
)

method=None (default) is byte-for-byte identical to the existing path.

Mean-aggregating rasterization + imshow interpolation collapses very
sparse images (mostly zeros, rare non-zero pixels) to near-black.
Adds method='datashader' + ds_reduction kwargs mirroring the existing
render_points/render_shapes API; routes the downsample step through
datashader.Canvas.raster with a configurable reduction (default 'max')
and forces nearest-neighbor display so the reduction is not re-smoothed.

Also centralizes the _DsReduction Literal (previously duplicated across
five sites) into render_params.py alongside a new _ImageDsReduction for
the image-only set ('mode', 'first', 'last' added; 'sum', 'any', 'count'
dropped since they're not valid Canvas.raster downsample methods).
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 20, 2026

Codecov Report

❌ Patch coverage is 95.65217% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.90%. Comparing base (3ebefe1) to head (ee32ffa).

Files with missing lines Patch % Lines
src/spatialdata_plot/pl/utils.py 88.88% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #676      +/-   ##
==========================================
+ Coverage   77.72%   77.90%   +0.17%     
==========================================
  Files          11       11              
  Lines        3641     3679      +38     
  Branches      860      868       +8     
==========================================
+ Hits         2830     2866      +36     
- Misses        486      487       +1     
- Partials      325      326       +1     
Files with missing lines Coverage Δ
src/spatialdata_plot/pl/_datashader.py 90.19% <100.00%> (-0.07%) ⬇️
src/spatialdata_plot/pl/basic.py 86.55% <100.00%> (+0.42%) ⬆️
src/spatialdata_plot/pl/render.py 87.36% <100.00%> (+0.09%) ⬆️
src/spatialdata_plot/pl/render_params.py 88.31% <100.00%> (+0.20%) ⬆️
src/spatialdata_plot/pl/utils.py 68.19% <88.88%> (+0.20%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

timtreis added 5 commits May 20, 2026 18:48
Five test_plot_* methods covering the high-signal cases for #449:
hero sparse-pixel test (default vs datashader=max side-by-side),
ds_reduction grid (max/min/mean/mode), multi-channel with per-channel
cmap, transfunc+cmap composition, and shapes-on-top composition.
Reference PNGs to be sourced from the next CI artifact run.
Drop the standalone TestRenderImagesDatashaderVisual class and its
sparse-data helper; add two test_plot_* methods directly to TestImages.
Keeps the two high-signal cases (hero side-by-side + reduction grid)
and drops the multichannel-cmap, transfunc, and shapes-overlay panels
whose code paths are already locked by non-visual tests.
- Rename render_images public kwarg ds_reduction -> datashader_reduction
  to match the existing render_points/render_shapes API; ImageRenderParams
  field name stays (matches the points/shapes internal field name).
- Bind get_args(_ImageDsReduction) once in the validation block.
- Mark the spatialdata.rasterize geometry-only call as a TODO for a
  future cheaper path.
- Redesign the reduction-grid visual test: mid-grey background +
  sparse bright pixels so max/min/mean/mode produce visibly distinct
  panels instead of nearly-identical stripes. Reference PNG to be
  regenerated from the next CI artifact run.
@timtreis
Copy link
Copy Markdown
Member Author

FYI @LucaMarconato

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: datashader also for images

2 participants